
% inputs: 
% filename: the full name of the .tif file to  be loaded
% frames: the frames you want to load; default is load all the frames
% frameaveraging: sometimes the metadata frameaveraging is wrong, so can
% hard code in what the real frame averaging is

function [mov,metadata] = loadTiffStack2_SI(filename,frames,frameaveraging)
% 

% newer version of scanimage has different .tif structure - this approach
% is much faster to read it but has to have all the associated functions on
% the path:
try
    if nargin > 1 && ~isempty(frames)
        [header,mov,c] = scanimage.util.opentif(filename,'frames',frames);
    else
        [header,mov,c] = scanimage.util.opentif(filename);
    end
    
    %format the metadata:
    metadata.zoom = header.SI.hRoiManager.scanZoomFactor;
    metadata.position = header.SI.hMotors.samplePosition;
    % as of 1/5/2023 new scanimage has a 1/2.5 conversion from the
    % "microns" it thinks and the microns it actually is. so all data from
    % the new scanimage (2022 or later) has to be scaled by that factor:
    if isa(c.si_ver,'double')
        metadata.position = metadata.position*2.5;
        metadata.position = metadata.position([2,1,3]);
    end
    metadata.si_version = c.si_ver;
    metadata.framerate = header.SI.hRoiManager.scanFrameRate;
    if length(header.SI.hChannels.channelSave) == 1
        metadata.frameaveraging = round(mean(diff(header.frameNumbers)));
    elseif length(header.SI.hChannels.channelSave) == 2
        temp = header.frameNumbers(1:2:end);
        metadata.frameaveraging = round(mean(diff(temp)));
    end
    if strcmp('loop',header.SI.acqState)
        metadata.numLoops = header.SI.acqsPerLoop;
    end
    if isfield(c,'numFrames')
        metadata.totalframes = c.numFrames*metadata.frameaveraging;
    else
        %metadata.totalframes = c.numImages*metadata.frameaveraging;
        metadata.totalframes = header.SI.hStackManager.framesPerSlice;
    end
    if isfield(c,'numLines')
        metadata.Height = c.numLines;
        metadata.Width = c.numPixels;
    else
        metadata.Height = size(mov,1);
        metadata.Width = size(mov,2);
    end
    metadata.savedchannels = header.SI.hChannels.channelSave;
    metadata.numZslices = header.SI.hStackManager.actualNumSlices;
    metadata.zStepSize = header.SI.hStackManager.actualStackZStepSize*2.5;
    
    %format the movie:
    if ndims(mov) == 4
        mov = double(permute(mov,[1,2,4,3]));
        if size(mov,4) == 1
            mov = mov(:,:,:,1);
        end
    end
    return;
catch
    disp('unable to do post 2020 scanimage loading')
end
    

metadata = getSImetadata(filename);
mImage = metadata.Width;
nImage = metadata.Height;
if nargin > 2 && ~isempty(frameaveraging)
    NumberImages = round(metadata.totalframes/frameaveraging)*length(metadata.savedchannels);
else
    %NumberImages = round(metadata.totalframes/metadata.frameaveraging)*length(metadata.savedchannels);
    NumberImages = round(metadata.totalframes*length(metadata.savedchannels)/metadata.frameaveraging);
end

if isfield(metadata,'numZslices') && metadata.numZslices > 1
    NumberImages = NumberImages *  metadata.numZslices;
end
    

if nargin < 2 || isempty(frames)
    frames = 1:NumberImages;
end
%mov=zeros(nImage,mImage,NumberImages,'uint16');
mov=zeros(nImage,mImage,length(frames),'uint16');



FileID = tifflib('open',filename,'r');
rps = tifflib('getField',FileID,Tiff.TagID.RowsPerStrip);



for i=1:length(frames)
   tifflib('setDirectory',FileID,frames(i)-1);
   % Go through each strip of data.
   rps = min(rps,nImage);
   for r = 1:rps:nImage
      row_inds = r:min(nImage,r+rps-1);
      stripNum = tifflib('computeStrip',FileID,r);
      mov(row_inds,:,i) = tifflib('readEncodedStrip',FileID,stripNum-1);
   end
end

tifflib('close',FileID);

mov = double(mov);
